package com.sip.stream.helper;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioRecordingConfiguration;
import android.media.audiofx.AcousticEchoCanceler;
import android.media.audiofx.NoiseSuppressor;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.util.Log;

import com.sip.stream.ClientApp;
import com.sip.stream.R;
import com.sip.stream.media.ZFYMediaManager;
import com.sip.stream.rxbus.RxBus;
import com.sip.stream.utils.zfy.callback.ZFYAudioRecordCallBack;
import com.sip.stream.utils.zfy.RxBusTag;
import com.sip.stream.utils.zfy.config.ZFYMediaConfig;
import com.sip.stream.utils.zfy.event.ZFYMediaEvent;
import com.sip.stream.utils.zfy.proxy.PlatformProxy;

import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.Single;
import io.reactivex.SingleObserver;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

public class AudioRecordHelper {
    private static final String TAG = "AudioRecordHelper";

    private AudioManager audioManager;
    private AudioRecord audioRecord;
    private Thread audioRecordThread;
    protected int audioSource;
    private Handler backgroundHandler;
    private HandlerThread backgroundThread;
    protected int bufferSize;
    protected ZFYAudioRecordCallBack callBack;
    private CompositeDisposable compositeDisposable;
    private AcousticEchoCanceler echoCanceler;
    private NoiseSuppressor noiseSuppressor;
    private int recordMode;
    private AudioManager.AudioRecordingCallback recordingCallback;
    private BroadcastReceiver scoBroadcastReceiver;
    private Semaphore audioRecordLock = new Semaphore(1);
    protected int sampleRate = 16000;
    protected int channelConfig = 16;
    protected int channelCount = 1;
    protected int audioFormate = 2;
    private int retryCount = 0;
    Disposable retryDisposable = null;
    int scoState = -1;
    private AtomicBoolean isRecording = new AtomicBoolean();

    public AudioRecordHelper(int i, ZFYAudioRecordCallBack zFYAudioRecordCallBack, Context context) {
        this.recordMode = 0;
        this.callBack = zFYAudioRecordCallBack;
        this.recordMode = i;
        this.audioManager = (AudioManager) context.getSystemService(ZFYMediaManager.ACTION_AUDIO);
        setupWatcher();
    }

    public AudioRecordHelper(int i, Context context) {
        this.recordMode = 0;
        this.recordMode = i;
        this.audioManager = (AudioManager) context.getSystemService(ZFYMediaManager.ACTION_AUDIO);
        setupWatcher();
    }

    private void setupWatcher() {
        AudioManager.AudioRecordingCallback audioRecordingCallback = new AudioManager.AudioRecordingCallback() {
            @Override
            public void onRecordingConfigChanged(List<AudioRecordingConfiguration> list) {
                super.onRecordingConfigChanged(list);
            }
        };
        this.recordingCallback = audioRecordingCallback;
        this.audioManager.registerAudioRecordingCallback(audioRecordingCallback, getBackgroundHandler());
    }

    private synchronized Handler getBackgroundHandler() {
        if (this.backgroundThread == null || this.backgroundHandler == null) {
            HandlerThread handlerThread = new HandlerThread("CameraBackground");
            this.backgroundThread = handlerThread;
            handlerThread.start();
            this.backgroundHandler = new Handler(this.backgroundThread.getLooper(), new Handler.Callback() {
                @Override
                public  boolean handleMessage(Message message) {
                    return false;
                }
            });
        }
        return this.backgroundHandler;
    }

    public synchronized void startRecord() {
        if (this.isRecording.get()) {
            return;
        }
        this.compositeDisposable = new CompositeDisposable();
        this.isRecording.set(true);
        createNewRecord();
        registerSCOStateListener();
    }

    private Context getContext() {
        return ClientApp.clientApp.getApplicationContext();
    }

    public void stopRecord() {
        Log.w(TAG, "stopRecord");
        if (this.isRecording.get()) {
            this.isRecording.set(false);
            stopNowRecord();
            if (this.scoBroadcastReceiver != null) {
                getContext().unregisterReceiver(this.scoBroadcastReceiver);
                this.scoBroadcastReceiver = null;
            }
            CompositeDisposable compositeDisposable = this.compositeDisposable;
            if (compositeDisposable != null) {
                compositeDisposable.dispose();
                this.compositeDisposable = null;
            }
            Single.timer(1L, TimeUnit.SECONDS).subscribe(new SingleObserver<Long>() {
                @Override
                public void onError(Throwable th) {
                }

                @Override
                public void onSubscribe(Disposable disposable) {
                }

                @Override
                public void onSuccess(Long l) {
                    PlatformProxy.getInstance().switchAudioRecordMode(0);
                }
            });
            AudioManager.AudioRecordingCallback audioRecordingCallback = this.recordingCallback;
            if (audioRecordingCallback != null) {
                this.audioManager.unregisterAudioRecordingCallback(audioRecordingCallback);
                this.recordingCallback = null;
            }
            this.callBack = null;
        }
    }

    public void changeMode(int i) {
        Log.w(TAG, "checkAudioMode: " + i);
        this.recordMode = i;
        if (getAudioSource() != this.audioSource) {
            Log.w(TAG, "changeMode true");
            this.retryCount = 0;
            if (stopNowRecord()) {
                Log.w(TAG, "wait for retry");
                return;
            }
            return;
        }
        Log.w(TAG, "changeMode false");
    }

    public boolean createNewRecord() {
        try {
            if (!this.audioRecordLock.tryAcquire(4L, TimeUnit.SECONDS)) {
                Log.i(TAG, "setUpCamera tryAcquire false");
                return false;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        PlatformProxy.getInstance().switchAudioRecordMode(1);
        AudioRecord upAudioRecord = setUpAudioRecord();
        this.audioRecord = upAudioRecord;
        if (upAudioRecord == null) {
            this.audioRecordLock.release();
            return false;
        }
        Thread thread = new Thread(new AudioRecordTask());
        thread.start();
        this.audioRecordThread = thread;
        this.audioRecordLock.release();
        return true;
    }

    public boolean stopNowRecord() {
        try {
            if (!this.audioRecordLock.tryAcquire(4L, TimeUnit.SECONDS)) {
                Log.i(TAG, "setUpCamera tryAcquire false");
                return false;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (this.audioRecordThread != null) {
            this.audioRecordThread.interrupt();
            this.audioRecordThread = null;
        }
        if (audioRecord != null) {
            audioRecord.stop();
            this.audioRecord.release();
            this.audioRecord = null;
        }
        ZFYMediaManager.getInstance().getStatus().setAudioSessionId(0);
        if (this.echoCanceler != null) {
            this.echoCanceler.setEnabled(false);
            this.echoCanceler.release();
            this.echoCanceler = null;
        }
        if ( this.noiseSuppressor != null) {
            this.noiseSuppressor.setEnabled(false);
            this.noiseSuppressor.release();
            this.noiseSuppressor = null;
        }
        this.audioRecordLock.release();
        return true;
    }

    private AudioRecord setUpAudioRecord() {
        ZFYMediaConfig config = ZFYMediaManager.getInstance().getConfig();
        int audioChanelCount = config.getAudioChanelCount();
        this.channelCount = audioChanelCount;
        if (audioChanelCount > 1) {
            this.channelConfig = 12;
        } else {
            this.channelConfig = 16;
        }
        int audioFormate = config.getAudioFormate();
        this.audioFormate = audioFormate;
        this.bufferSize = AudioRecord.getMinBufferSize(this.sampleRate, this.channelConfig, audioFormate) * 2;
        AudioFormat build = new AudioFormat.Builder().setSampleRate(this.sampleRate).setEncoding(2).setChannelMask(16).build();
        this.audioSource = getAudioSource();
        AudioRecord build2 = new AudioRecord.Builder().setAudioSource(this.audioSource).setAudioFormat(build).setBufferSizeInBytes(this.bufferSize).build();
        Log.i("audioTest", "new AudioRecord");
        Log.i(TAG, "audioSource: " + this.audioSource + " audioFormat:" + build.toString());
        int state = build2.getState();
        if (state != 1) {
            Log.e(TAG, "audioRecord getState():" + state);
            ZFYAudioRecordCallBack zFYAudioRecordCallBack = this.callBack;
            if (zFYAudioRecordCallBack != null) {
                zFYAudioRecordCallBack.onError(ClientApp.clientApp.getApplicationContext().getString(R.string.audio_recording_openfailed));
            }
            try {
                build2.release();
                return null;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
        Log.i(TAG, "audioRecord create success: " + build2.getAudioSessionId());
        try {
            build2.startRecording();
            Log.i("audioTest", "tAudioRecord startRecording");
        } catch (Exception e) {
            e.getLocalizedMessage();
        }
        Log.w(TAG, "audioRecord getRecordingState(): " + build2.getState() + " getRecordingState: " + build2.getRecordingState());
        if (build2.getRecordingState() != 3) {
            checkStatusLater();
        }
        for (AudioRecordingConfiguration audioRecordingConfiguration : this.audioManager.getActiveRecordingConfigurations()) {
            if (audioRecordingConfiguration.getClientAudioSessionId() == build2.getAudioSessionId()) {
                Log.i(TAG, "" + build2.getAudioSessionId() + " isActive");
            }
        }
        if (this.recordMode == 1) {
            if (useAcousticEchoCanceler(config)) {
                ZFYMediaManager.getInstance().getStatus().setAudioSessionId(build2.getAudioSessionId());
                AcousticEchoCanceler create = AcousticEchoCanceler.create(build2.getAudioSessionId());
                this.echoCanceler = create;
                create.setEnabled(true);
                Log.i(TAG, "AcousticEcho Canceler create AudioSessionId: " + build2.getAudioSessionId());
                RxBus.getDefault().post(new ZFYMediaEvent(ZFYMediaEvent.EVENT_TYPE_ACOUSTIC_ECHO_OPEN), RxBusTag.MEDIA_EVENT);
            } else {
                Log.i(TAG, "AcousticEchoCanceler isAvailable false");
                RxBus.getDefault().post(new ZFYMediaEvent(ZFYMediaEvent.EVENT_TYPE_ACOUSTIC_ECHO_OPEN), RxBusTag.MEDIA_EVENT);
            }
        } else {
            Log.i(TAG, "AcousticEchoCanceler close");
            ZFYMediaManager.getInstance().getStatus().setAudioSessionId(0);
        }
        if (useNoiseSuppressor(config)) {
            NoiseSuppressor create2 = NoiseSuppressor.create(build2.getAudioSessionId());
            this.noiseSuppressor = create2;
            if (create2 != null) {
                create2.setEnabled(true);
                Log.i(TAG, "NoiseSuppressor enable true" + build2.getAudioSessionId());
            } else {
                Log.i(TAG, "NoiseSuppressor.create false" + build2.getAudioSessionId());
            }
        } else {
            Log.i(TAG, "useNoiseSuppressor isAvailable false");
        }
        return build2;
    }

    private boolean useAcousticEchoCanceler(ZFYMediaConfig zFYMediaConfig)
    {
        return zFYMediaConfig.isAcousticEchoCanceler() && AcousticEchoCanceler.isAvailable();
    }

    private boolean useNoiseSuppressor(ZFYMediaConfig zFYMediaConfig) {
        return zFYMediaConfig.isNoiseSuppressor() && NoiseSuppressor.isAvailable();
    }

    private void checkStatusLater() {
        Log.i(TAG, "checkStatusLater");
        Single.timer(3L, TimeUnit.SECONDS).subscribe(new SingleObserver<Long>() {
            @Override
            public void onError(Throwable th) {
            }

            @Override
            public void onSubscribe(Disposable disposable) {
            }

            @Override
            public void onSuccess(Long l) {
                Log.w(TAG, "checkStatusLater audioRecord getRecordingState(): " + AudioRecordHelper.this.audioRecord.getState() + " getRecordingState: " + AudioRecordHelper.this.audioRecord.getRecordingState());
                if (AudioRecordHelper.this.audioRecord.getRecordingState() != 3) {
                    AudioRecordHelper.this.retry();
                }
            }
        });
    }

    public void retry() {
        Log.i(TAG, "retry stopRecording");
        int i = this.retryCount;
        if (i < 10) {
            this.retryCount = i + 1;
            Disposable disposable = this.retryDisposable;
            if (disposable != null) {
                disposable.dispose();
            }
            Observable.timer(32L, TimeUnit.MILLISECONDS).repeat(50L).subscribe(new Observer<Object>() {
                @Override
                public void onSubscribe(Disposable disposable2) {
                    AudioRecordHelper.this.retryDisposable = disposable2;
                    AudioRecordHelper.this.compositeDisposable.add(disposable2);
                }

                @Override
                public void onNext(Object obj) {
                    AudioRecordHelper.this.processBuffer(new byte[1024]);
                }

                @Override
                public void onError(Throwable th) {
                    Log.i(AudioRecordHelper.TAG, "onError");
                }

                @Override
                public void onComplete() {
                    Log.i(AudioRecordHelper.TAG, "setUpAudioRecord");
                    AudioRecordHelper.this.createNewRecord();
                }
            });
            return;
        }
        Log.i(TAG, "stop record");
    }

    public class AudioRecordTask implements Runnable {
        private AudioRecordTask() {
        }

        @Override
        public void run() {
            byte[] bArr = new byte[1024];
            Arrays.fill(bArr, (byte) 0);
            AudioRecordHelper.this.processBuffer(bArr);
            while (AudioRecordHelper.this.isRecording.get() && AudioRecordHelper.this.audioRecord != null && !Thread.interrupted()) {
                if (AudioRecordHelper.this.audioRecord.read(bArr, 0, 1024) > 0) {
                    AudioRecordHelper.this.processBuffer(bArr);
                }
            }
            if (AudioRecordHelper.this.isRecording.get()) {
                AudioRecordHelper.this.retry();
            }
        }
    }

    public void processBuffer(byte[] bArr) {
        ZFYAudioRecordCallBack zFYAudioRecordCallBack = this.callBack;
        if (zFYAudioRecordCallBack != null) {
            zFYAudioRecordCallBack.onAudioStream(bArr);
        }
    }

    private int getAudioSource() {
        Log.i(TAG, "getAudioSource " + this.recordMode);
        int i = 3;
        int i2 = 7;
        if (!isWiredHeadsetOn() && this.recordMode != 1) {
            i = 0;
            i2 = 1;
        }
        AudioManager audioManager = this.audioManager;
        if (audioManager != null && audioManager.getMode() != i) {
            Log.i(TAG, "audioManager.setMode from " + this.audioManager.getMode() + " to " + i);
            this.audioManager.setMode(i);
        }
        return i2;
    }

    private boolean isWiredHeadsetOn() {
        AudioManager audioManager = this.audioManager;
        if (audioManager == null) {
            return false;
        }
        return !audioManager.isSpeakerphoneOn();
    }

    private void registerSCOStateListener() {
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("android.media.ACTION_SCO_AUDIO_STATE_UPDATED");
        ClientApp.clientApp.getApplicationContext().registerReceiver(getSCOBroadcastReceiver(), intentFilter);
    }

    private BroadcastReceiver getSCOBroadcastReceiver() {
        if (this.scoBroadcastReceiver == null) {
            this.scoBroadcastReceiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (intent == null || intent.getAction() == null || !intent.getAction().equals("android.media.ACTION_SCO_AUDIO_STATE_UPDATED")) {
                        return;
                    }
                    int intExtra = intent.getIntExtra("android.media.extra.SCO_AUDIO_STATE", -1);
                    Log.w(AudioRecordHelper.TAG, "ACTION_SCO_AUDIO_STATE_UPDATED state" + intExtra);
                    if (intExtra == 1 || intExtra == 0) {
                        if (AudioRecordHelper.this.scoState == -1) {
                            AudioRecordHelper.this.scoState = intExtra;
                            return;
                        }
                        AudioRecordHelper.this.scoState = intExtra;
                        if (AudioRecordHelper.this.stopNowRecord()) {
                            AudioRecordHelper.this.createNewRecord();
                        }
                    }
                }
            };
        }
        return this.scoBroadcastReceiver;
    }
}
